home *** CD-ROM | disk | FTP | other *** search
-
- /* File: /usr/em/Kernel/Em/main.c July 8th, 1985 Emerald kernel main.c */
-
- /*
- * $Header$
- *
- * em [ -N lnn ] [ -x debug_level ] [ -t trace_level ] \
- * [ -d dimension ] [ -k configurefile ]
- *
- * This module is designed to be used as the main loop for Eden kernel.
- *
- * Higher debug levels give more information. For now the debug info
- * comes out on the error output. This needs to be changed.
- * There is also a Prod facility which may be used to get a stalled
- * kernel process to print out a little bit of data concerning it's state.
- * This state information only concerns signal handling.
- *
- * The dimension parameter will put the host/pod into the specified
- * dimension, default is 0. For testing separate Eden systems only.
- * Not intended for use other than Message Module testing.
- *
- * This is really a kind of multi-tasking exec. Tasks can specify
- * handlers for various events. They can then queue the event, or let
- * a Unix signal queue the event. The main loop just checks the queue
- * for unhandled events and calls the handler. This insures that the
- * handlers will be called in the same order in which the events occured.
- *
- * The configure file parameter may be used to change the name of the
- * default configure file searched for.
- * It contains pairs of name and new value for integers. Note that
- * the setting of these values happen early - before initialization routines
- * are called. -- Eric Jul, 1984-05-16.
- *
- * TaskQ is a queue holding events that need to be handled. Events
- * are put on by RealSigHandler as a result of a signal. They are taken
- * off by the main loop as each one is handled.
- *
- * FreeQ is the free list.
- *
- * The interpreter is built into the mainLoop of the kernel:
- * The mainLoop is in a separate source file.
- *
- *
- * 10 Nov 82 Originally written by Jim Rees
- * 15 Dec 83 Major rewrite for one process kernel by J. Sanislo
- * 06 Jul 84 Changes made to switch from use of Unix 4.1 to 4.2 signals
- * 01 Aug 84 Split out MainLoop procedure into a separate file.
- * 08 Jul 85 Initial modification to become an Emerald kernel.
- */
- char *nodeKind =
- "Emerald Node";
-
- #define ROOTDIR "/scratch/eric/emerald/"
-
- #ifdef RCSID
- static char rcsid[] = "$Header$";
- #endif
- #include <stdio.h>
- #include <signal.h>
- #include <pwd.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #ifdef xkernel
- #include "userupi.h"
- #include "userprocess.h"
- #else
- #include <netdb.h>
- #endif
-
- #include "Kernel/h/assert.h"
-
- #undef integer /* Silly stdtypes */
- #include "Kernel/h/system.h"
- #include "Kernel/h/stdTypes.h"
- #include "Kernel/h/mmCodes.h"
- #include "Kernel/h/mmTypes.h"
- #include "Kernel/h/mmMsgDefs.h"
- #include "Kernel/h/mmMsgTypes.h"
- #include "Kernel/h/kBootCodes.h"
- #include "Kernel/h/kEvents.h"
- #include "Kernel/h/hotsTypes.h"
- #include "Kernel/h/kmdDefs.h"
- #include "Kernel/h/kmdTypes.h"
- #include "Kernel/h/emPorts.h"
- #include <errno.h>
- #include "Kernel/h/ecTypes.h"
- #include "Kernel/h/emTypes.h"
-
- #define EMKERNELVERSION "Version 10.00"
- #define EMKERNELVERSIONDATE " @(#)main.c 1.9 2/23/90"
-
- extern int *VarLookup();
- /* extern int *sprintf(); Removed because stdio.h does it */
-
- #define SIGPROD 31
- #define SIGDBXPROD 30
- #define CONFFILE "emrc"
-
- /*
- * The following are `constant' strings defined at
- * node start up time.
- */
- char EMDIR[100]; /* Home directory for user USERNAME,
- e.g. "/usr/em/" */
-
- char progArg0Name[100]; /* Name of kernel program. */
-
- extern char vMMEtherDevName[];
-
- #ifndef NODISK
- char NODEDIR[100]; /* Node directory,
- e.g. "/usr/em/Nodes/HN0001/" */
- char nodisk; /* diskless kernel can be had at compile time
- * with -DNODISK or runtime with nodisk!=0
- */
- #endif
-
- time_t nodeIncarnationId; /* IncarnationId: use ctime(3) */
- time_t cEmVersion = EMVERSION; /* Software version control (ctime(3)) */
-
- /* "forward" */
- extern void MainLoop();
- extern void shutdownOID();
- extern void SetLNN();
-
- extern void FLInit(), EmInit(), ItemInit();
-
- extern EmBadSignal();
- int emPlane = 0;
- int emPort = EMKERNELDEFAULTPORTNUMBER;
-
- /*
- * Routines to initialize main data structures.
- */
-
- char myHostName[100];
- FILE *logout; /* fp for log file */
- int IamPOD; /* obsolete and should go. */
- NodeNum defaultCS; /* Default checksite for created ejects */
- int onlyFindingOIDs = 0;
-
- /*
- * Define auxilliary signal stack.
- * The purpose of this stack is to avoid having ULTRIX signal handlers
- * running on Emerald process stacks.
- */
-
- #define SIGSTACKSIZE 10000 /* integers */
-
- long signalstack[SIGSTACKSIZE];
-
- /* Table of physical machine string names and ethernet addresses */
- #ifdef WASHINGTON
- #define NUMEMMACHINES 12
- char *EmMachineNames[NUMEMMACHINES] =
- {
- "whistler", "skagit", "bezier", "taber", "larry",
- "june", "krakatoa", "roskilde", "tahiti", "beaver",
- "wally", "crystal"
- };
- #endif
- #ifdef ARIZONA
- #define NUMEMMACHINES 5
- char *EmMachineNames[NUMEMMACHINES] =
- {
- "megaron", "arizona", "bocklin", "lectura",
- "jenson"
- };
- #endif
- #ifdef DIKU
- #define NUMEMMACHINES 5
- char *EmMachineNames[NUMEMMACHINES] =
- {
- "diku", "thor", "roar", "bjarke", "regnar"
- };
- #endif
-
- EtherNetAddress EmMachineAddrs[NUMEMMACHINES], myEtherAddr;
- int NumEmMachines = NUMEMMACHINES;
-
- int SigIntHandler();
- int ProdHandler();
- int DBXProdHandler();
-
- checkEnvironment()
- {
- char *emplanename;
- extern char *getenv();
-
- emplanename = getenv("EMPLANE");
- if (emplanename != NULL) {
- emPlane = atoi(emplanename);
- if (emPlane < 0 || emPlane > 100) {
- printf("Invalid EMPLANE %s\n", emplanename);
- exit(1);
- }
- }
- }
-
- void
- computeEmPort()
- {
- struct servent *myService;
- #ifdef DIKU
- myService = getservbyname(EMKERNELSERVICEPORT, "tcp");
- if(myService)
- emPort = ntohs(myService->s_port);
- #endif
- emPort += emPlane*4;
- }
-
- /*
- *
- * SetFlush
- *
- * Snapshot to turn flushing of stdout on/off.
- *
- */
- /* Snapshot */
- void SetFlush(fInt, fString)
- int fInt;
- char *fString;
- {
- if(!strcmp(fString, "on")) {
- setlinebuf(stdout);
- KMDPrint("Flushing turned on.\n");
- } else
- if(!strcmp(fString, "off")) {
- setbuf(stdout,NULL);
- KMDPrint("Flushing turned off.\n");
- } else {
- KMDPrint("Option %s not understood.");
- }
- }
-
-
- /*
- * This is it! The main program of the Emerald kernel process.
- */
-
- #ifdef xsun3
- kbd_demux()
- {
- xkhandlerstart();
- xkhandlerend();
- }
-
- kbd_other()
- {
- xkhandlerstart();
- xkhandlerend();
- }
-
- initKeyboard()
- {
- static struct {
- char *addr;
- int len;
- } whom = { 0 , 0 };
- int foo;
- SESSN bar;
- foo = xcreateprotl(kbd_demux, kbd_other, kbd_other);
- if (foo < 0)
- printf("main: xcreateprotl failed\n");
- bar = xopen(foo, KBD, whom);
- if (bar < 0) {
- printf("main: xopen KBD failed\n");
- } else {
- printf("main: xopen KBD worked\n");
- }
- }
- #endif
-
- #ifndef xkernel
- main(ac,av)
- int ac;
- char *av[];
- #else
- user(ac,av)
- int ac;
- char *av[];
- #endif
- {
- int i, traceLevel = 3;
- int Dimension =0; /* which Ethernet dimension used. */
- KKStatus lStatus;
- extern void GCInit();
- #ifndef xkernel
- struct sigvec vec; /* used in sigvec() calls */
- struct sigstack theStackInfo;
- /* Variable for Search for full argv[0] pathname. */
- char pathstring[100], *chp, *pathptr, confBuf[140];
- #define STBUFHASBEENDECLARED
- struct stat stbuf;
- int found = 0;
- FILE *cfp; /* Configure parameter file. */
- #endif
- Boolean nodeNumSeen = FALSE;
- char *confFileName;
- int argc;
- Boolean standAlone = FALSE;
- #ifndef STBUFHASBEENDECLARED
- #ifndef NODISK
- FILE *cfp;
- struct stat stbuf;
- char confBuf[140];
- #endif NODISK
- #endif STBUFHASBEENDECLARED
- /*
- * DataBrand is defined in ecTypes.h and used in kstub.4s
- * If you change the value of DataBrand, do it in both those places
- * and here too.
- */
-
- assert(0 == (int) DataBrand);
-
- #ifndef NOFLUSHSTDOUT
- setbuf(stdout,NULL);
- #endif /* NOFLUSHSTDOUT */
-
- GCInit();
- #ifdef xkernel
- initXK();
- #endif
-
- checkEnvironment();
- computeEmPort();
- /* Fill in Em machine string name / ethernet address table */
- for (i = 0; i < NumEmMachines; i++) {
- if(!mSUCCESS(
- mMakeEtherNetAddr(EmMachineNames[i],
- EMKERNELSERVICEPORT, emPort,
- &(EmMachineAddrs[i]) )) )
- {
- bzero((char *) &EmMachineAddrs[i], sizeof(EmMachineAddrs[i]));
- }
- }
-
- /*
- * Set file protection mask.
- */
- #if defined(BSD) || defined (xsimul)
- (void) umask(0); /* rwx for everybody */
- #endif
- #ifdef OLDEDEN
- /* Find the home directory for user Em */
- if ((edenpw = getpwnam(USERNAME)) == NULL) {
- ErrMsg("No user account for '%s' on this machine\n", USERNAME);
- exit(1);
- }
- (void) strcpy(EMDIR, edenpw->pw_dir);
- (void) strcat(EMDIR,"/");
- #else OLDEDEN
- (void) strcpy(EMDIR, ROOTDIR);
- #endif OLDEDEN
-
- /*
- * Find full path name of argv[0] file.
- */
- #ifdef xkernel
- strcpy(progArg0Name, av[0]);
- #else
- (void) strcpy(progArg0Name, av[0]);
- if ( (av[0][0] == '.') || (av[0][0] == '/') ) {
- /* av[0] name ok. */
- found++;
- }
- else {
- /* Search through PATH to find full path name. */
- pathptr = getenv("PATH");
- do {
- chp = pathstring;
- while( (*pathptr != ':') && (*pathptr != '\0') ) {
- *chp++ = *pathptr++;
- }
- *chp++ = '/'; *chp = '\0';
- (void) strcat(pathstring,av[0]);
- if ( !stat(pathstring,&stbuf) ) {
- found++;
- break;
- }
- if ( *pathptr == ':' ) pathptr++;
- } while( *pathptr != '\0' );
-
- if ( found ) (void) strcpy(progArg0Name, pathstring);
- }
- #endif
-
- /*
- * Configuration file: Before doing anything really try finding
- * and reading in a configuration file.
- * We scan the options TWICE.
- */
-
- argc = ac;
- confFileName = CONFFILE;
-
- while (ac > 1) {
- if (av[1][0] == '-') switch (av[1][1]) {
- #ifndef NODISK
- case 'k': /* Set configuration file name. */
- confFileName = av[2];
- ac--; av++; /* Skip over actual name. */
- break;
- #endif
- case 'E':
- (void) strcpy(EMDIR, av[2]);
- ac--; av++; /* Skip over actual name */
- break;
-
- }
- ac--;
- av++;
- }
- av -= (argc - ac); ac = argc; /* Restore option ptr. for 2nd pass. */
-
- #ifndef NODISK
- if(!nodisk) {
- if ( (cfp = fopen(confFileName, "r")) == (FILE *) NULL ) {
- /* No user configure file - find system. */
- (void) strcpy(confBuf, EMDIR);
- (void) strcat(confBuf, CONFFILE);
- confFileName = confBuf;
- cfp = fopen(confFileName, "r");
- }
-
- if ( cfp != NULL ) { /* Found a configure file. */
- /* Now go thru it and read stuff out of it. */
- /* Rehacked Sept. 1988 so that strings can */
- /* be used too. */
- char varName[140], someString[140];
- int varValue, *varAddr;
-
- printf(" Configure file: %s\n", confFileName);
-
- (void) fscanf(cfp, "#%*[^\n]%*c"); /* Skip rest of line. */
-
- while (fscanf(cfp, "%139s %139s", varName, someString) != EOF) {
-
- (void) fscanf(cfp, "%*[^\n]%*c"); /* Skip rest of line. */
-
- if ( varName[0] == '#' ) continue; /* Skip comment. */
-
- if ( someString[0] == '"' ) {
- int length;
- length = strlen(someString);
- if (length > 0) length--; /* Null out end-quote */
- someString[length] = '\0';
-
- /* Lookup variable name and set value. */
- if ((varAddr = VarLookup(varName)) == (int *) -1) {
- ErrMsg(">> Configure var %s not found - ignored\n",
- varName);
- continue;
- };
- printf(" var %s (0x%08x) = \"%s\"\n", varName, varAddr,
- &someString[1]);
- strcpy(varAddr, &someString[1]);/* Actually assign it. */
- continue;
- }
-
- /* Lookup variable name and set value. */
- if (sscanf(someString, "%d", &varValue) != 1) {
- ErrMsg(">> Configure var %s assigned bad value %s\n",
- varName, someString);
- }
-
- if ((varAddr = VarLookup(varName)) == (int *) -1) {
- ErrMsg(">> Configure var %s not found - ignored\n",
- varName);
- continue;
- };
- printf(" var %s (0x%08x) = %d\n", varName, varAddr,
- varValue);
- *varAddr = varValue; /* Actually assign it. */
- };
- (void) fclose(cfp);
- };
-
- #endif NODISK
- /*
- * Parse command line options
- */
- while (ac > 1 && av[1][0] == '-') {
- switch (av[1][1]) {
- case 'N': /* Set logical node number */
- if ( nodeNumSeen ) {
- ErrMsg(">>> Node number multiply defined.\n");
- exit(0);
- }
- if (av[1][2] == '\0') {
- i = atoi(av[2]);
- ac--;
- av++;
- } else
- i = atoi(&av[1][2]);
- SetLNN( i );
- nodeNumSeen = TRUE;
- break;
- case 'k': /* Configure file name: skip it. */
- ac--; av++;
- break;
- case 'E': /* Directory for kernel to use and find builtins */
- /* Emerald dir name: skip it. */
- ac--; av++;
- break;
- case 's': /* Stand alone mode: no HOTS stuff nor
- Ethernet */
- standAlone = TRUE;
- break;
- case 'x': /* debugmsg tracing to stdout */
- if (av[1][2] == '\0') {
- DebugLevel = atoi(av[2]);
- ac--;
- av++;
- } else
- DebugLevel = atoi(&av[1][2]);
- break;
- case 'l': /* trace level for -T and -S */
- if (av[1][2] == '\0') {
- traceLevel = atoi(av[2]);
- ac--;
- av++;
- } else
- traceLevel = atoi(&av[1][2]);
- break;
- case 'T': /* Set a trace to stdout */
- case 'S': /* Set a trace to stdout */
- if (av[1][2] == '\0') {
- KMDPrepareTrace(av[2], traceLevel);
- ac--;
- av++;
- } else
- KMDPrepareTrace(&av[1][2], traceLevel);
- break;
- case 'j': /* Define name of ethernet device */
- if (av[1][2] == '\0') {
- (void) strcpy(&vMMEtherDevName[0], av[2]);
- KMDPrepareTrace(av[2], traceLevel);
- ac--;
- av++;
- } else
- (void) strcpy(&vMMEtherDevName[0], &av[1][2]);
- break;
- case 't': /* MM tracing */
- if (av[1][2] == '\0') {
- MMTrace = atoi(av[2]);
- ac--;
- av++;
- } else
- MMTrace = atoi(&av[1][2]);
- break;
-
- case 'o': /* Only find the OIDs in the checkpoint files */
- onlyFindingOIDs = 1;
- break;
-
- case 'd': /* Dimension */
- if (av[1][2] == '\0') {
- Dimension = atoi(av[2]);
- ac--;
- av++;
- } else
- Dimension = atoi(&av[1][2]);
- break;
- }
- ac--;
- av++;
- }
-
- if (gethostname( myHostName, sizeof(myHostName) ) == -1) {
- #ifdef BSD
- fflush(stdout); fflush(stderr);
- #endif
- perror("gethostname");
- abort();
- }
-
- DebugMsg(2, "Using port %d\n", emPort);
-
- if (!nodeNumSeen) {
- if (!mSUCCESS(mMakeEtherNetAddr(myHostName, EMKERNELSERVICEPORT,
- emPort, &myEtherAddr)))
- {
- ErrMsg("Could not generate node number\n");
- abort();
- }
-
- SetLNN(MachineAddress(*(struct in_addr *)&myEtherAddr));
- }
- (void) sprintf( MMTraceHost, "Em%02x", GetLNN());
-
- #ifdef xsun3
- initKeyboard();
- #endif
-
- /* Turn on TRACING here */
- KMDTest = 0;
- i = nodeIncarnationId = time((time_t *) 0);
- printf("\n Emerald kernel : %s of %s\n", EMKERNELVERSION,
- EMKERNELVERSIONDATE);
- printf(" Emerald version : %s", ctime(&cEmVersion));
- printf(" Starting on : %s", ctime((time_t *)&i) );
- printf(" Physical node : %s\n", myHostName);
- printf(" Logical node : %d (0x%02x) \n", GetLNN(), GetLNN());
- printf(" Emplane : %d (0x%02x) \n", emPlane, emPlane);
- printf(" Kernel loadfile : %s\n", progArg0Name);
- printf(" Debug Level : %d, Message Trace Level: %d\n",
- DebugLevel, MMTrace );
- if (Dimension) printf(" Dimension : %d\n", Dimension);
-
- #ifdef OLDEDEN
- /*
- * Get LNN of public pod on our diskserver. This is LNN
- * we willll use in UIDs for created ejects.
- *
- * ASSUMPTIONS:
- * 1. myHostName still contains the result of the gethostname
- * call made above.
- * 2. A diskservers entry in /etc/hosts contains an
- * alias of form "xND" for each machine x (including
- * itself) to which it provides disk service.
- * Each Vax is considered to be its own diskserver.
- */
- diskserver = (void) strcat(myHostName, "ND"); /* this clobbers myHostName! */
- hp = gethostbyname( diskserver );
- if ( hp == NULL ) {
- printf("No host entry for %s.\n", diskserver);
- exit(0);
- }
- defaultCS = (NodeNum) defaultLnn( hp->h_addr[3], (int) True );
- printf (" Default CS for created ejects: %d (dec)\n", defaultCS );
- #endif OLDEDEN
-
- #ifndef NODISK
- if(!nodisk) {
- (void) sprintf(NODEDIR, "%sNodes/Em%04x", EMDIR, NodeNumber);
- printf(" Node directory : %s\n", NODEDIR);
- /* Make sure the node directory exists */
- if ( stat(NODEDIR, &stbuf) < 0 ) {
- if ( (errno == ENOENT) && ( mkdir(NODEDIR, 0777) == 0 ) ) {
- ErrMsg("No temp directory. Created %s\n",NODEDIR);
- } else {
- ErrMsg("Cannot create temp directory %s\n", NODEDIR);
- fflush(stdout); fflush(stderr);
- perror("stat/mkdir");
- exit( 1 );
- }
- } else {
- if ( ! (stbuf.st_mode & S_IFDIR) ) {
- ErrMsg("%s already exists and is not a directory.\n",NODEDIR);
- exit( 1 );
- }
- }
- DebugMsg(5, "EMDIR: %s\n",EMDIR);
- DebugMsg(5, "NODEDIR: %s\n",NODEDIR);
- }
- #endif NODISK
-
- #ifndef xkernel
- /*
- * Define an alternate stack where ULTRIX signal handlers may
- * execute.
- */
-
- theStackInfo.ss_sp = (caddr_t) &signalstack[SIGSTACKSIZE-2];
- theStackInfo.ss_onstack = 0;
- if (sigstack(&theStackInfo, NULL) == -1) {
- fflush(stdout); fflush(stderr);
- perror("sigstack");
- abort();
- }
-
- #endif xkernel
-
- /* If we are killed, shut down gracefully */
- #ifdef xkernel
- xonfault(SigIntHandler);
- #else
- vec.sv_handler = SigIntHandler;
- vec.sv_mask = 0; /* All signals enabled */
- vec.sv_onstack = 1; /* Auxiliary stack specified */
- sigvec(SIGINT, &vec, 0); /* 0 means do not tell me old sighandler */
- vec.sv_handler = SigIntHandler;
- sigvec(SIGTERM, &vec, 0);
-
- /* Set handler to catch NIL references in Emerald programs */
- vec.sv_handler = EmBadSignal;
- sigvec(SIGILL, &vec, 0);
- sigvec(SIGBUS, &vec, 0);
- sigvec(SIGSEGV, &vec, 0);
-
- /* Define prod handlers. */
- vec.sv_handler = ProdHandler;
- sigvec(SIGPROD, &vec, 0);
- vec.sv_handler = DBXProdHandler;
- sigvec(SIGDBXPROD, &vec, 0);
- #endif
-
- /* Initialize the task queues */
- initqueue((struct Queue *) &FreeQ);
- initqueue((struct Queue *) &TaskQ);
- for (i = 0; i < MAXTASKQ; i++)
- enqueue((struct Queue *) &FreeQ, (struct Queue *) &TaskArray[i]);
-
- if (!standAlone) {
-
- /*
- * Call protocol initialization routines
- */
-
- /* InitHOTS() also initializes the message module. */
- /* Define dimension first, however. */
- lStatus = MMDefineDimension(Dimension);
- if ( !mSUCCESS( lStatus ) ) {
- ErrMsg("Dimension out of wack: %08x...\n",lStatus);
- exit( 1 );
- }
- i = IsActiveNode |
- #if defined(vax)
- IsVax
- #endif
- #if defined(sun)
- IsSun
- #endif
- ;
-
- {
- InitHOTS(emPort);
-
- /* Initialize KMD */
- KMDInit( htons(emPort + 1) );
- /* Initialize fileload */
- FLInit((unsigned short) htons(emPort + 2) );
- }
- }
-
- /*
- * Install the SetFlush snapshot.
- */
- KMDSetSnap(SetFlush);
-
- BootKernel( i );
-
- #ifndef NODISK
- if (!nodisk) {
- char logfile [100];
- (void) sprintf (logfile, "%s/log", NODEDIR);
- if ((logout = fopen (logfile, "a")) == NULL)
- ErrMsg ("Cannot open log file %s\n", logfile);
- }
-
- #endif NODISK
- EmInit();
- /* Never return */
-
-
- /*************************************************************/
- /* E N D O F I N I T I A L I Z A T I O N S */
- /*************************************************************/
- }
- }
-
- /*
- * SigIntHandler()
- *
- * This routine gets called whenever the either kernel process gets
- * shut down. If we are process A, we just exit. If we are B,
- * we send a SIGINT to A and exit.
- *
- * Undocumented "feature" (bug?): In 4.1bsd, the signal number is the
- * first argument to the handler. In 4.2bsd, it IS documented.
- *
- * Try to send a shutdown message. I don't know if this will work,
- * because the task queue has been stopped, but do it anyway.
- */
-
- SigIntHandler(fSig, fCode, fContext)
- int fSig;
- int fCode;
- struct sigcontext *fContext;
- /* For param description, see sigvec(2), ULTRIX manual */
- {
- static char *sigprint[] = {
- "Hangup", "Interrupt", "Quit", "Illegal instruction",
- "Trace trap", "IOT", "EMT", "FPE",
- "Kill", "Bus error", "Segmentation violation",
- "Bad arg to sys call", "Broken pipe", "Alarm clock",
- "Terminated", "Em IPC",
- };
- char *message, buf[40];
- #ifndef xkernel
- struct sigvec vec;
- int sig;
- #endif
-
- HoldSigs(); /* Watch out for this */
- #ifndef xkernel
- (void) fflush(stdout);(void) fflush(stderr);
- #endif
- if (fSig > 0 && fSig <= 16)
- message = sigprint[fSig - 1];
- else {
- (void) sprintf(buf, "Unknown signal %d", fSig);
- message = buf;
- }
-
- printf(
- "**** Signal no. %d (%s) arrived -- starting termination.\n",
- fSig, message);
-
- SendShutDownMsg(GetLNN());
-
- shutdownOID();
-
- #ifndef xkernel
- /*
- * If this is an unexpected signal, get a core dump.
- * Have to reset signals to default action first.
- */
- if (fSig != SIGINT && fSig != SIGTERM) {
- printf( "IP = 0x%04x, Code = %d\n", fContext->sc_pc,
- fCode);
- vec.sv_handler = SIG_DFL;
- vec.sv_mask = 0;
- vec.sv_onstack = 0;
- #ifdef BSD
- for (sig = 1; sig < NSIG; sig++)
- (void) sigvec(sig, &vec, 0);
- printf( "Core dumped\n");
- (void) sigsetmask(0);
- if (fSig == SIGQUIT) {
- int *dummy = (int *) -1;
- *dummy = 0;
- }
- #endif
- return; /* and UNIX will do the right thing */
- }
- #endif
- printf( "Termination done -- exiting.\n");
- exit(0); /* For some unknown reason, exit(0) can cause
- a segmentation fault in _fwalk */
- }
-
- /*
- * ProdHandler()
- *
- * Can be called by sending the process an interrupt.
- * The idea is to be able to 'prod' a stalled process and possibly learn
- * why it stalled.
- * WARNING: This procedure may be called anytime - the signal for it
- * must never be held - and therefore it cannot rely on a consistent state
- * of the data structures of the kernel.
- */
- int ProdHandler()
- {
- int i;
-
- #ifdef xsimul
- printf( "\nProd of %s%04x (pid = %d)\n", "EmeraldNode", GetLNN(), getpid());
- #else
- printf( "\nProd of %s%04x\n", "EmeraldNode", GetLNN());
- #endif
- printf( "SigsHeld = %2d\n", SigsHeld);
- printf( "shouldPause = %s\n",
- shouldPause == reallyPause ? "reallyPause" : "dontPause");
- printf( "Pending = %2d\n", Pending);
- printf( "ActCount = %2d\n", ActCount);
- printf( "Status of held signals:\n");
- printf( "Seq. no. Signal no. Count\n");
- for (i=0; i < ActCount; i++) {
- printf( " %4d %4d %4d\n",
- i, ActSig[i], SigTable[ActSig[i]].Ntimes);
- }
- printf( "CurrentSSP 0x%08x", currentSSP);
- if (NonNULL(currentSSP)) {
- printf( " processOID 0x%08x", currentSSP->processOID);
- }
- printf( "\n*** End Prod ***\n");
- }
-
- /* Does nothing on a kill -30; can be used to get dbx attention
- * by setting a break point here, e.g., stop in DBXProdHandler
- */
- int DBXProdHandler()
- {
- }
-